<template>
    <div class="map"></div>
</template>

<script setup>
import { onMounted, ref, watch } from 'vue';
import Map from 'ol/Map';
import View from 'ol/View';
import TileLayer from 'ol/layer/Tile';
import { XYZ } from 'ol/source';
import 'ol/ol.css';
import { Style, Fill, Stroke, Icon, Circle } from 'ol/style';
import VectorLayer from 'ol/layer/Vector';
import VectorSource from 'ol/source/Vector';
import GeoJSON from 'ol/format/GeoJSON';
import { useStore } from '@/stores/index.js';
import Draw from 'ol/interaction/Draw';
import { getLength, getArea, getDistance } from 'ol/sphere';
import Overlay from 'ol/Overlay';
import Feature from 'ol/Feature';
import { Point } from 'ol/geom';
import Cluster from 'ol/source/Cluster';
import Text from 'ol/style/Text';

let clusterSource = null;
let clusterLayer = null;

let drawSource = null;
let drawLayer = null;

const store = useStore();
let cityAdcode = ref('');
const center = ref([]);
let map = null;
let style = '';
let geometryType = '';
let draw = null;

let iconSource = null;

// 获取数据
async function getData() {
    await store.axiosData();
    await store.mapJson();
    // 城市的中心点坐标
    center.value = store.center;

    // 获取城市的adcode值
    cityAdcode.value = store.cityAdcode;
    return cityAdcode;
}

onMounted(async () => {
    await getData();
    addMap(center.value);
    // 页面加载完成之后跳转到指定城市的中心坐标点
    map.getView().animate({
        center: center.value,
        zoom: 9,
        duration: 2000,
    });
});

// 监听中心点变化
watch(
    () => store.center,
    async (newCenter) => {
        if (map && Array.isArray(newCenter) && newCenter.length === 2) {
            // 重新加载城市边界图层
            const adcode = store.cityAdcode;
            // 移除旧的城市边界图层
            map.getLayers()
                .getArray()
                .forEach((layer) => {
                    if (layer instanceof VectorLayer && layer.get('name') === 'cityLayer') {
                        map.removeLayer(layer);
                    }
                });
            // 添加新的城市边界图层
            const cityLayer = new VectorLayer({
                source: new VectorSource({
                    url: `https://geo.datav.aliyun.com/areas_v3/bound/${adcode}.json`,
                    format: new GeoJSON(),
                }),
                style: new Style({
                    fill: new Fill({
                        color: 'rgba(255, 0, 0, 0.2)',
                    }),
                    stroke: new Stroke({
                        color: 'black',
                        width: 2,
                    }),
                }),
            });
            cityLayer.set('name', 'cityLayer');
            map.addLayer(cityLayer);
            // 添加跳转动画
            map.getView().animate({
                center: newCenter,
                zoom: 9,
                duration: 2000,
            });
        }
    }
);
// 监听绘制draw类型
watch(
    () => store.drawType,
    (newValue) => {
        store.addIcon = ''; // 清除图标选择
        if (draw) {
            map.removeInteraction(draw);
            draw = null;
        }
        if (newValue) {
            if (newValue === 'line' || newValue === 'FreeLine') {
                geometryType = 'LineString';
                style = new Style({
                    stroke: new Stroke({
                        color: 'blue',
                        width: 2,
                    }),
                });
            }
            if (newValue === 'polygon') {
                geometryType = 'Polygon';
                style = new Style({
                    fill: new Fill({
                        color: 'rgba(255, 0, 0, 0.2)',
                    }),
                    stroke: new Stroke({
                        color: 'green',
                        width: 2,
                    }),
                });
            }
            if (newValue === 'circle') {
                geometryType = 'Circle';
                style = new Style({
                    fill: new Fill({
                        color: 'rgba(255, 0, 0, 0.2)',
                    }),
                });
            }
            if (newValue === 'clear') {
                drawSource.clear();
                document.querySelectorAll('#overlay').forEach((el) => {
                    el.remove();
                });
                return;
            }
        }
        if (geometryType) {
            draw = new Draw({
                source: drawSource,
                type: geometryType,
                style: style,
                freehand: newValue === 'FreeLine',
            });
            map.addInteraction(draw);
        }
        draw.on('drawend', (e) => {
            const f = e.feature;
            const g = f.getGeometry();
            const overlay = document.createElement('div');
            overlay.id = 'overlay';
            const overl = new Overlay({
                element: overlay,
            });
            map.addOverlay(overl);
            overlay.style.backgroundColor = 'rgba(0, 0, 0, 0.5)';
            overlay.style.color = 'white';
            overlay.style.padding = '5px';
            overlay.style.borderRadius = '5px';
            // 线段
            if (g.getType() === 'LineString') {
                let length = getLength(g, { projection: 'EPSG:4326' });
                if (length >= 1000) {
                    length = (length / 1000).toFixed(2);
                    overlay.innerHTML = `长度: ${length} km`;
                } else {
                    length = length.toFixed(2);
                    overlay.innerHTML = `长度: ${length} m`;
                }
                const coordinate = g.getCoordinates()[g.getCoordinates().length - 1];
                overl.setPosition(coordinate);
            }
            // 多边形
            if (g.getType() === 'Polygon') {
                let area = getArea(g, { projection: 'EPSG:4326' });
                if (area >= 1000000) {
                    area = (area / 1000000).toFixed(2);
                    overlay.innerHTML = `面积: ${area} km²`;
                } else {
                    area = area.toFixed(2);
                    overlay.innerHTML = `面积: ${area} m²`;
                }
                const coords = g.getCoordinates()[0];
                const coordinate = coords[coords.length - 1];
                overl.setPosition(coordinate);
            }
            // 圆形
            if (g.getType() === 'Circle') {
                // 计算半径（米）
                const center = g.getCenter();
                const radiusDeg = g.getRadius();
                const edgePoint = [center[0] + radiusDeg, center[1]];
                const radius = getDistance(center, edgePoint).toFixed(2);
                const area = (Math.PI * Math.pow(radius, 2)).toFixed(2);
                if (radius >= 1000 && area >= 1000000) {
                    overlay.innerHTML = `半径: ${(radius / 1000).toFixed(2)} km<br>面积: ${(
                        area / 1000000
                    ).toFixed(2)} km²`;
                } else {
                    overlay.innerHTML = `半径: ${radius} m<br>面积: ${area} m²`;
                }
                overl.setPosition(edgePoint);
            }
        });
    }
);
// 监听添加图标
let lastIconClickHandler = null;
watch(
    () => store.addIcon,
    (newValue) => {
        // 先清除绘制交互，防止添加icon时还能绘制
        if (draw) {
            map.removeInteraction(draw);
            draw = null;
        }
        store.drawType = '';
        // 解绑上一次的 click 事件
        if (lastIconClickHandler) {
            map.un('click', lastIconClickHandler);
            lastIconClickHandler = null;
        }
        if (newValue === 'clear') {
            iconSource.clear();
            clusterSource.clear();
        }
        // 定义点击事件
        const iconClickHandler = (e) => {
            const coordinate = e.coordinate;
            let iconPath = '';
            let name = '';
            if (newValue === 'gas_station') {
                iconPath = '/加油站.svg';
                name = '加油站';
            } else if (newValue === 'charging_station') {
                iconPath = '/充电站.svg';
                name = '充电站';
            } else if (newValue === 'parking_lot') {
                iconPath = '/停车场.svg';
                name = '停车场';
            }
            if (iconPath) {
                const iconFeature = new Feature({
                    geometry: new Point(coordinate),
                    name,
                });
                iconFeature.setStyle(
                    new Style({
                        image: new Icon({
                            src: iconPath,
                            scale: 1,
                        }),
                    })
                );
                iconSource.addFeature(iconFeature);
            }
        };
        map.on('click', iconClickHandler);
        lastIconClickHandler = iconClickHandler;
    }
);

// 聚合图形显示逻辑
function clusterStyle() {
    return (f) => {
        const size = f.get('features').length;
        let style = new Style();
        if (size === 1) {
            // 取聚合内唯一 feature 的 style 或自定义图标
            const feature = f.get('features')[0];
            const iconStyle = feature.getStyle();
            if (iconStyle) {
                style = iconStyle;
            } else {
                // 默认用 feature 的 name 判断用哪个图标
                let iconPath = '/logo.svg';
                const name = feature.get('name');
                if (name === '加油站') iconPath = '/加油站.svg';
                if (name === '充电站') iconPath = '/充电站.svg';
                if (name === '停车场') iconPath = '/停车场.svg';
                style.setImage(
                    new Icon({
                        src: iconPath,
                        scale: [0.5, 1],
                    })
                );
            }
        } else {
            style.setImage(
                new Circle({
                    radius: 10,
                    stroke: new Stroke({
                        color: 'black',
                    }),
                    fill: new Fill({
                        color: '#3399CC',
                    }),
                })
            );
            style.setText(
                new Text({
                    text: size.toString(),
                    fill: new Fill({
                        color: '#fff',
                    }),
                })
            );
        }
        return style;
    };
}
// 添加地图
function addMap(num) {
    map = new Map({
        target: document.querySelector('.map'),
        view: new View({
            center: num, // 动态设置中心点坐标
            projection: 'EPSG:4326',
            zoom: 5,
        }),
    });
    // 雷打不动的高德地图
    const layer = new TileLayer({
        source: new XYZ({
            url: 'http://wprd0{1-4}.is.autonavi.com/appmaptile?lang=zh_cn&size=1&style=7&x={x}&y={y}&z={z}',
        }),
    });
    map.addLayer(layer);
    // 添加adcode值添加指定城市边界
    const cityLayer = new VectorLayer({
        source: new VectorSource({
            url: `https://geo.datav.aliyun.com/areas_v3/bound/${cityAdcode.value}.json`,
            format: new GeoJSON(),
        }),
        // 设置样式 描边+半透明填充
        style: new Style({
            fill: new Fill({
                color: 'rgba(255, 0, 0, 0.2)',
            }),
            stroke: new Stroke({
                color: 'black',
                width: 1,
            }),
        }),
    });
    cityLayer.set('name', 'cityLayer');
    map.addLayer(cityLayer);
    drawSource = new VectorSource();
    drawLayer = new VectorLayer({
        source: drawSource,
        style: new Style({
            fill: new Fill({
                color: 'rgba(255, 0, 0, 0.2)',
            }),
            stroke: new Stroke({
                color: 'black',
                width: 2,
            }),
        }),
    });
    map.addLayer(drawLayer);

    iconSource = new VectorSource();
    clusterSource = new Cluster({
        distance: 50,
        source: iconSource,
    });
    clusterLayer = new VectorLayer({
        source: clusterSource,
        style: clusterStyle(),
    });
    map.addLayer(clusterLayer);

    // 图层显示/隐藏 实时更新zoom的值,在header中根据zoom的值来禁用/启用图标框的点击
    map.getView().on('change:resolution', () => {
        const zoom = map.getView().getZoom();
        store.zoom = zoom;
        if (zoom > 15) {
            map.getLayers().forEach((layer) => {
                if (layer instanceof VectorLayer && layer.get('name') === 'cityLayer') {
                    layer.setVisible(false);
                }
            });
        } else {
            map.getLayers().forEach((layer) => {
                if (layer instanceof VectorLayer && layer.get('name') === 'cityLayer') {
                    layer.setVisible(true);
                }
            });
        }
    });
}
</script>

<style scoped>
.map {
    width: 100%;
    height: calc(100vh - 100px); /* 计算高度,因为header给的高度是100px */
}
</style>
